package com.beauty.inventory.service.impl;

import com.beauty.inventory.service.RateLimiterService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Service
@RequiredArgsConstructor
@Slf4j
public class RedissonRateLimiterServiceImpl implements RateLimiterService {

    private final RedissonClient redissonClient;
    private final ConcurrentMap<String, RRateLimiter> rateLimiterMap = new ConcurrentHashMap<>();
    
    private static final String RATE_LIMITER_KEY_PREFIX = "rate:limiter:";

    @Override
    public boolean tryAcquire(String key, double rate, int permits) {
        String limiterKey = RATE_LIMITER_KEY_PREFIX + key;
        log.info("【Redisson限流器】准备获取限流器，key: {}, 速率: {}/s, 请求令牌数: {}", key, rate, permits);
        
        RRateLimiter rateLimiter = getRateLimiter(limiterKey, rate);
        
        try {
            boolean acquired = rateLimiter.tryAcquire(permits);
            if (acquired) {
                log.info("【Redisson限流器】成功获取令牌，key: {}, 令牌数: {}, 可用令牌数: {}", 
                        key, permits, rateLimiter.availablePermits());
            } else {
                log.warn("【Redisson限流器】获取令牌失败，已达到限流阈值，key: {}, 请求令牌数: {}, 可用令牌数: {}", 
                        key, permits, rateLimiter.availablePermits());
            }
            return acquired;
        } catch (Exception e) {
            log.error("【Redisson限流器】获取令牌异常，key: {}, 令牌数: {}, 异常: {}", key, permits, e.getMessage(), e);
            // 发生异常时默认放行，避免影响正常业务
            return true;
        }
    }

    @Override
    public boolean tryAcquire(String key, double rate) {
        return tryAcquire(key, rate, 1);
    }
    
    /**
     * 获取或创建限流器
     */
    private RRateLimiter getRateLimiter(String key, double rate) {
        return rateLimiterMap.computeIfAbsent(key, k -> {
            String config = "无法获取配置";
            try {
                config = redissonClient.getConfig().toJSON();
            } catch (IOException e) {
                log.error("【Redisson限流器】获取配置信息异常", e);
            }
            log.info("【Redisson限流器】创建新的限流器实例，key: {}, Redisson配置: {}", k, config);
            RRateLimiter rateLimiter = redissonClient.getRateLimiter(k);
            try {
                // 尝试初始化限流器（如果已存在则不会重新设置）
                boolean success = rateLimiter.trySetRate(RateType.OVERALL, (int) rate, 1, RateIntervalUnit.SECONDS);
                log.info("【Redisson限流器】初始化限流器{}，key: {}, rate: {}/s, 当前配置: {}", 
                        success ? "成功" : "已存在", key, rate, 
                        success ? "新建" : rateLimiter.getConfig().toString());
            } catch (Exception e) {
                log.error("【Redisson限流器】初始化限流器失败，key: {}, rate: {}/s, 异常: {}", key, rate, e.getMessage(), e);
            }
            return rateLimiter;
        });
    }
} 